This documentation explains how to add support for your own custom made components, and already existing components that are not yet supported in the current Hack The Planet version. It is a little long winded but the tools are very easy to use once you understand them.

You can add support for your own components in your mod's modmain.lua file now. I have spent a lot of time making and streamlining tools so they will be very easy to use, and I will explain each one to make them as clear as possible.


First, you should be aware of the recommended shortener. It will make writing the code a lot easier and faster. From modmain.lua, it goes like this:
local tools=GLOBAL.GetPlayer().HUD.htp.tools


Assuming you're using the shortener above, these are the tools:
tools:registercomponent(component name, function)
tools:setbutton(component name, button name, button text, text color, x,y,z, button's function)
tools:hideallbuttons()
tools:exithtpmode()
tools:resethbuttonplacement()
tools:returnnextline()
tools:returnxpos(current button, total buttons)
tools:menuheader()
tools:menufooter()
tools:return2dplaces(num)
tools:returnboolstring(var)
tools:returnboolstringinvert(var)

Variables:
tools.target


Tool Descriptions:
Now I will explain each tool and it's arguments. After that, I will show an example of how the tools are used.

---------------
registercomponent(component name, function)
You MUST use this tool if you want HTP to check for your component.

-component name: This field is case-sensitive(capitalization matters), MUST not contain any spaces and MUST match the name of the component. It expects a string value, so this field must also be surrounded in quotation marks. Both fields must be present and this tool can only be used once for each component. Using it again for the same component will overwrite that component's function. I will explain the "function" field in a bit.
---------------


---------------
setbutton(component name, button name, button text, text color, x,y,z, button's function)
This tool is the most complicated but most useful of the bunch. It's used to create new buttons and edit already existing buttons.

-component name: This field is required and MUST match the same "component name" given in the registercomponent() tool. The same rules apply for both "component name" fields. In other words, no spaces, must be in quotes, is case-sensitive, and must match the name of the component. If you want to add support for an existing component, such as health, hunger or locomotor, you simply put their name in this field.

-button name: This field is also mandatory. It will be the name of the button and each button needs a different name. Let me say that again. No two buttons can share the same name, so make the name as unique as possible. If the name given has already been used, it will apply all arguments given to that button. It too must be surrounded in quotation marks, not contain any spaces, and is case sensitive.

-button text: This field denotes what text will be displayed on the button. You can use strings, variables, or functions that return a string or variable. This field is required and can't be nil, however, if you want the button to be blank, you can just use " ".

-text color: This field determines the color of the text. It expects an RGBA table, which can be written as {1,.5,185/255,1}. If you're familiar with RGB colors, you'll have no trouble with this. The last value in the table is the alpha value, 1 is recommended. You can also pick a color from my list of presets: "blue", "purple", "green", "red", "aqua". These colors match the default HTP button text colors, which means if I change the color of green to something brighter in future updates, any buttons you colored green will automatically change too. When using a preset, it must also be a string, meaning surrounded by quotation marks. This field is NOT required so if you want to use the default text color, you can simply use nil.

-x,y,z: These fields determine the button's location. The X field is by far the most complicated. Which is why I made the tool, returnxpos(). See that tool's description, or the example at the bottom, to better understand it. But before you use returnxpos(), know that using the value of 0 will put the button in the middle. So if you just want a single button on one line, save yourself the effort and just use 0 in this field. The Y field determines it's location vertically. The tool returnnextline() vastly simplifies this field. I haven't experiment with the Z field, but I can tell you giving it a value of 0 is perfectly acceptable. All of HTP's buttons use a 0 in this field and it has never been a problem. All 3 fields are not mandatory, UNLESS you're setting the function.

-button's function: This is where you put the code you want to run when the button is clicked. This field is not required. It's pretty self explanatory but again, see the example below to get a basic idea of what you can do with this.
---------------


---------------
hideallbuttons()
This tool hides ALL buttons. Sometimes you might need to use this tool when making submenus, and to prevent the user from clicking a button that attempts to alter an entity that doesn't exist anymore (which could crash the game).
---------------


---------------
exithtpmode()
This tool is similar to hideallbuttons(), except it also exits "Hacker Mode". Sometimes you might need to use this if you want something to happen as soon as a button is clicked, before the user has a chance to respond.
---------------


---------------
returnnextline()
This tool is used for button vertical placement. More specifically, it's used in conjunction with the Y value in the setbutton() tool. In a nutshell, it's basically the same as pressing the enter key on your keyboard in a word processor. The example code will better show it's two main uses.
---------------


---------------
returnxpos(current button, total buttons)
Because setbutton()'s X field might be a bit too much for some people, this tool takes a lot of the guess work out of it. It's used for when you want to put multiple buttons on the same line. We'll get to that later.

-current button: This is the current button on the line, starting from left to right. It must be a number and not a string, variable or table.

-total buttons: This is the total number of buttons you're going to have on one line. It must be a number and not a string, variable or table.
---------------


---------------
resethbuttonplacement()
This tool is similar to returnnextline(), except it resets the vertical button placement location back to the top. If you're making a new submenu, you'll need to use this so new buttons will appear at the top.
---------------


---------------
menuheader()
This tool is used to automatically add the header buttons. It's also used for submenus. As of this writing, the header is solely the entity in question's name/prefab button.
---------------


---------------
menufooter()
Much like the menuheader() function, this automatically adds the footer buttons. It too is used for submenus. Right now, it sets the duplicate, delete, close and resume buttons.
---------------


---------------
return2dplaces(num)
This function returns a numerical value that's a max of two decimal places long. For example, this code:
local x=12.3456
x=return2dplaces(x)
print(x)
will give an output of 12.34. It's useful for information buttons.
---------------


---------------
returnboolstring(var)
This function expects a boolean value and returns a string based on that variable. Giving it the value of true, it will return the string "On". If the value is false, it will return the string "Off". Again, this is a tool for information buttons.
---------------


---------------
returnboolstringinvert(var)
Much like returnboolstring(), this tool expects a boolean value and returns a string, except the value is inverted. Giving the value of true will return the string "Off", and a value of false will return "On". Still for information buttons. And yes, believe it or not, some buttons are more logical with this.
---------------



Variable Descriptions:
---------------
-tools.target
When someone enters "Hacker Mode" and clicks a valid entity, that entity is stored in this variable. If you need to change something about the selected entity, use this as it's reference. For example, when the user clicks a rabbit, you can change how much health that rabbit has with:
tools.target.components.health:DoDelta(999)
It's the same as using 'inst' in a prefab file. It's most useful inside of button functions.
---------------



Whew! Finally got past all of that! Is anyone still awake? I hope so. Now let's move on to the example. Below is an actual working example of the code I used to add support for a custom made component. I used the mod "Wormhole Marks", only because it was the first mod I came across that adds it's own component. Again, I will go through this step by step, explaining each line so you can understand everything based on it's usage. If you would like to see images of the code in action, copy and paste these links into your browser:
https://www.dropbox.com/s/fm6p1f137pgvbsx/custom%20buttons%20example.jpg
https://www.dropbox.com/s/xlgtrj8fxbd7ems/custom%20submenu%20example.jpg



--This line is needed to make sure the code won't run until all mods are loaded and the game is running:
AddSimPostInit(function(inst)

	--We add this line because we want to be sure Hack The Planet is installed and running in the current session. Otherwise the game will crash:
	if GLOBAL.GetPlayer().HUD.htp then


		--Below is the shortener I talked about earlier. It HAS to be INSIDE the AddSimPostInit() function because it references something that doesn't exist until all mods are loaded:
		local tools=GLOBAL.GetPlayer().HUD.htp.tools

		--Now we need to make the function that acts as a container for the menus. You can name it whatever you want, but remember registercomponent() only accepts one function per component:
		local function mymenu()

			--Now we will create a very simple button:
			tools:setbutton("wormhole_marks", "button1", "This is a button", nil, 0,tools:returnnextline(),0, function()
				print("The first button was clicked. The code placed in this function will now run.")
			end)

			--That last button doesn't do much so let's make this button a little more advanced:
			tools:setbutton("wormhole_marks", "button2", "This is another button", nil, 0,tools:returnnextline(),0, function()
				print("The second button was clicked.")
				print("The code placed here will now run.")

				--As you might suspect, the code inside this block doesn't run UNTIL this button is clicked.
				local number=0
				number=number+1

				--The line below updates the button. As you can see, since we're only changing the text of the button, you do NOT need to reenter all of the arguments all over again. You've probably guessed the text of the button will read "1" after the button is pressed. You may also notice the "button's text" field is not a string.
				tools:setbutton("wormhole_marks", "button2", number)
			end)

			--The last button was still pretty bland. Let's step up our game and change the value of a component. Again, the "button's text" field in the line below contains a string, a function and a variable, and it still works wonderfully:
			tools:setbutton("wormhole_marks", "ismarked", "Marking is "..tools:returnboolstring(tools.target.components.wormhole_marks.marked), "purple", 0,tools:returnnextline(),0, function()

				--Let's make this button toggle one of the component's already existing variables between true and false:
				if tools.target.components.wormhole_marks.marked==true then
					tools.target.components.wormhole_marks.marked=false
				else
					tools.target.components.wormhole_marks.marked=true
				end

				--Since we changed the value of the variable, this button needs to be updated to reflect the change. Notice, again, we don't need to reenter anything beyond the button's text field:
				tools:setbutton("wormhole_marks", "ismarked", "Marking is "..tools:returnboolstring(tools.target.components.wormhole_marks.marked))
			end)

			--You may have noticed all buttons above are on their own separate line. But how do we make all of the buttons on the same line? Like so:
			local sameline=tools:returnnextline()

			--Now every button that uses the local variable "sameline" in it's "Y" field in the setbutton() function, will be on the same line. Pay attention to the "X" fields below as well.
			tools:setbutton("wormhole_marks", "leftbutton", "Left Button", "green", tools:returnxpos(1,3),sameline,0, function()
				print("The button on the left was clicked.")
			end)
			tools:setbutton("wormhole_marks", "middlebutton", "Middle Button", "purple", tools:returnxpos(2,3),sameline,0, function()
				print("The button in the middle was clicked.")
			end)
			tools:setbutton("wormhole_marks", "rightbutton", "Right Button", "red", tools:returnxpos(3,3),sameline,0, function()
				print("The button on the right was clicked.")
			end)

			--Super! Now we know how to arrange buttons, both vertically and horizontally, but what about making a whole new menu? Well, first we make a button that will close the previous menu and open the submenu:
			tools:setbutton("wormhole_marks", "optionsmenu1", "Option Menu", nil, 0,tools:returnnextline(),0, function()
				print("This button was clicked and will now hide the previous menu(s) and open a new one.")

				--We don't want a bunch of ugly overlapping buttons so we'll use the tool below to hide them:
				tools:hideallbuttons()

				--We also want the new submenu to display it's buttons at the top, instead of where ever the last button defined left off, so we'll use this tool:
				tools:resethbuttonplacement()

				--This line adds the header buttons, which currently is just the name/prefab button. We add it so the user doesn't get confused about what they're editing:
				tools:menuheader()

				--Now we add the submenu buttons. Right now they're pretty bare bones, but you should get the idea:
				tools:setbutton("wormhole_marks", "submenubutton1", "Submenu Button1", nil, 0,tools:returnnextline(),0, function()
					print("The first button was clicked. The code placed in this function will now run.")
				end)
				tools:setbutton("wormhole_marks", "submenubutton2", "Submenu Button2", nil, 0,tools:returnnextline(),0, function()
					print("The second button was clicked. The code placed in this function will now run.")
				end)

				--When finishing up a submenu, we add the footer buttons. Again, we add them for consistency, cosmetic appeal and to provide the user basic functionality.
				tools:menufooter()
			end)
		end

		--Finally, and most importantly, we use the tool below to register our custom made component with HTP and to tell it what function the component should be linked to. This has to be done BEFORE closing the AddSimPostInit function. Notice the first value is the same name as the first value in all setbutton() functions. The second value is the same as the name of the function above:
		tools:registercomponent("wormhole_marks", mymenu)
	end
end)



And we're all done! Wasn't that fun? Now let's remove all the comments and useless junk buttons and see how it looks:

AddSimPostInit(function(inst)
	if GLOBAL.GetPlayer().HUD.htp then
		local function mymenu()
			local tools=GLOBAL.GetPlayer().HUD.htp.tools
			tools:setbutton("wormhole_marks", "ismarked", "Marking is "..tools:returnboolstring(tools.target.components.wormhole_marks.marked), "purple", 0,tools:returnnextline(),0, function()
				if tools.target.components.wormhole_marks.marked==true then
					tools.target.components.wormhole_marks.marked=false
				else
					tools.target.components.wormhole_marks.marked=true
				end
				tools:setbutton("wormhole_marks", "ismarked", "Marking is "..tools:returnboolstring(tools.target.components.wormhole_marks.marked))
			end)
		end
		tools:registercomponent("wormhole_marks", mymenu)
	end
end)


Well that's not so scary looking now, is it? Nope! In fact, it's down right simple! Or at least it is in comparison to HTP's code. But could it be simpler? You bet it can!


AddSimPostInit(function(inst)
	if GLOBAL.GetPlayer().HUD.htp then
		local thecomp="wormhole_marks"
		local tools=GLOBAL.GetPlayer().HUD.htp.tools
		local function mymenu()
			tools:setbutton(thecomp, "ismarked", "Marking is "..tools:returnboolstring(tools.target.components.wormhole_marks.marked), "purple", 0,tools:returnnextline(),0, function()
				if tools.target.components.wormhole_marks.marked==true then
					tools.target.components.wormhole_marks.marked=false
				else
					tools.target.components.wormhole_marks.marked=true
				end
				tools:setbutton(thecomp, "ismarked", "Marking is "..tools:returnboolstring(tools.target.components.wormhole_marks.marked))
			end)
		end
		tools:registercomponent(thecomp, mymenu)
	end
end)

Did you notice the difference this time? You would if you had to use the setbutton() function over and over. It's a good idea to set that variable. It prevents typos, cuts down on time spent coding and makes it easier to read. It also makes the above block a great template to copy-paste into your modmain.lua. ;)

Well, that's the basics of everything you need to know! You should now be able to make custom menus with ease! Enjoy!

Advanced Modders:
If you're experienced with making and editing HUD components and you would like to edit the button values directly, all buttons are stored in:
GetPlayer().HUD.htp.plugins.<the given component name>.<the given button name>
